﻿using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using Titan.Test.Entity;
using System.Data;
using Titan.Oracle;
using Titan.SqlServer;
using Titan;

namespace Titan.Test
{
    
    
    /// <summary>
    ///这是 DbSessionTest 的测试类，旨在
    ///包含所有 DbSessionTest 单元测试
    ///</summary>
    [TestClass]
    public class DynamicEntityTest
    {
        private readonly IDbSession _session;
        private readonly Dictionary<string, string> _tableMapping;

        public DynamicEntityTest()
        {
            _session = Environment.OpenSession();
            _tableMapping = Environment.TableMapping; 


            
        }

        private static string[] ToStringArray(PropertyExpression[] ps)
        {
            List<string> list = new List<string>();
            foreach (PropertyExpression p in ps)
            {
                list.Add(p.PropertyName);
            }
            return list.ToArray();
        }
        /// <summary>
        ///Insert 的测试
        ///</summary>
        [TestMethod]
        public void InsertTest()
        {
            DynamicEntity enrity = new DynamicEntity("Area");

            enrity["AreaName"] = "Testa中文 " + Guid.NewGuid().ToString();
            enrity["ParentAreaId"] = 0;

            _session.Insert(_tableMapping, enrity);


            //取回当前id符合名称的id
            object value = _session.ExecuteScalar("select AreaId from Test_Area where AreaName='" + enrity["AreaName"] + "'");
            int expected = _session.ConvertDatabaseValue<int>(value);
            Assert.AreEqual(expected, enrity.Get<int>("AreaId"));

            //取回最大id 
            value = _session.ExecuteScalar("select max(AreaId) from Test_Area");
            expected = _session.ConvertDatabaseValue<int>(value);
            Assert.AreEqual(expected, enrity.Get<int>("AreaId"));
            
        }
        /// <summary>
        ///测试insert时排除某些字段
        ///</summary>
        [TestMethod]
        public void InsertTest_Exclude()
        {
            //customertype表的CustomerTypeName字段有默认值:'dft'
            DynamicEntity enrity = new DynamicEntity("Area");
            enrity["AreaName"] = "Testa中文 " + Guid.NewGuid().ToString();
            enrity["ParentAreaId"] = 0;

            _session.Insert(_tableMapping, enrity, new string[]{ "AreaName"});
             
            //取回当前id符合名称的id
            object value = _session.ExecuteScalar("select AreaName from Test_Area where areaId=" + enrity["AreaId"] + "");
            string actual = _session.ConvertDatabaseValue<string>(value);
            string expected = "dft";
            Assert.AreEqual(expected, actual);
             

        }


        /// <summary>
        /// 测试更新所有字段
        /// </summary>
        [TestMethod]
        public void UpdateTest()
        {
            DynamicEntity enrity = new DynamicEntity("Area");
            enrity["AreaName"] = "Testa中文 " + Guid.NewGuid().ToString();
            enrity["ParentAreaId"] = 9;
            _session.Insert(_tableMapping, enrity);

            DynamicEntity enrity2 = new DynamicEntity("Area");
            enrity2["AreaId"] = enrity["AreaId"];
            enrity2["AreaName"] = Guid.NewGuid().ToString();
            enrity2["ParentAreaId"] = 3456;
            _session.Update(_tableMapping, enrity2,ToStringArray( AreaProp.ALL));

            

            //取回
            string expectedName = enrity2.Get<string>("AreaName");
            object valueName = _session.ExecuteScalar("select AreaName from Test_Area where AreaId=" + enrity2["AreaId"] + "");
            string actualName = _session.ConvertDatabaseValue<string>(valueName); 
            Assert.AreEqual(expectedName, actualName);

            //取回最大id 
            int expectedParentAreaId = enrity2.Get<int>("ParentAreaId");
            object valueParentAreaId = _session.ExecuteScalar("select ParentAreaId from Test_Area where AreaId=" + enrity2["AreaId"] + "");
            int actualParentAreaId = _session.ConvertDatabaseValue<int>(valueParentAreaId);
            Assert.AreEqual(expectedParentAreaId, actualParentAreaId);

        }

        /// <summary>
        /// 测试更新所有字段
        /// </summary>
        [TestMethod]
        public void UpdateTest_SpecifiedProperties()
        {
            DynamicEntity enrity = new DynamicEntity("Area");
            enrity["AreaName"] = "Testa中文 " + Guid.NewGuid().ToString();
            enrity["ParentAreaId"] = 9;
            _session.Insert(_tableMapping, enrity);


            DynamicEntity enrity2 = new DynamicEntity("Area");
            enrity2["AreaId"] = enrity["AreaId"];
            enrity2["AreaName"] = Guid.NewGuid().ToString();
            enrity2["ParentAreaId"] = 3456;
            _session.Update(_tableMapping, enrity2, new string[]{"areaName"});



            //取回
            string expectedName = enrity2.Get<string>("AreaName");
            object valueName = _session.ExecuteScalar("select AreaName from Test_Area where AreaId=" + enrity2["AreaId"] + "");
            string actualName = _session.ConvertDatabaseValue<string>(valueName);
            Assert.AreEqual(expectedName, actualName);

            //取回最大id 
            int expectedParentAreaId = enrity.Get<int>("ParentAreaId");
            object valueParentAreaId = _session.ExecuteScalar("select ParentAreaId from Test_Area where AreaId=" + enrity2["AreaId"] + "");
            int actualParentAreaId = _session.ConvertDatabaseValue<int>(valueParentAreaId);
            Assert.AreEqual(expectedParentAreaId, actualParentAreaId);

        }
        [TestMethod]
        public void DeleteTest()
        {
            DynamicEntity enrity = new DynamicEntity("Area");
            enrity["AreaName"] = "Testa中文 " + Guid.NewGuid().ToString();
            enrity["ParentAreaId"] = 9;
            _session.Insert(_tableMapping, enrity);

            //执行删除
            DynamicEntity enrity2 = new DynamicEntity("Area");
            enrity2["AreaId"] = enrity["AreaId"];
            _session.Delete(_tableMapping, enrity2);
             
             

            //是否还存在这个id  
            bool actual = _session.RecordExists("select * from Test_Area where AreaId=" + enrity["AreaId"] + ""); 
            Assert.AreEqual(false, actual);

        }

        [TestMethod]
        public void BatchUpdateTest_SingleTable()
        {
            //先添加几条记录，然后批量修改
            int minId = 0;
            List<DynamicEntity> list = new List<DynamicEntity>();
            for (int i = 0; i < 5; i++)
            {
                DynamicEntity obj = new DynamicEntity("Area");
                obj["AreaName"] = "Testa中文 " + Guid.NewGuid().ToString();
                obj["ParentAreaId"] = 9;
                _session.Insert(_tableMapping, obj);
                list.Add(obj);
                if (i == 0) minId = obj.Get<int>("AreaId");
            }

            //执行修改
            ConditionCollection cs = new ConditionCollection();
            cs.Add("areaId", ConditionOperator.GreaterThanOrEqual, minId);


            DynamicEntity obj2 = new DynamicEntity("Area");
            obj2["AreaName"] = "update" + Guid.NewGuid().ToString();
            _session.BatchUpdate(_tableMapping, obj2, cs, "areaname");



            //是否还存在这个id  
            foreach (DynamicEntity item in list)
            {
                string expected = obj2.Get<string>("AreaName");
                object value = _session.ExecuteScalar("select AreaName from Test_Area where AreaId=" + item["AreaId"] + "");
                string actual = _session.ConvertDatabaseValue<string>(value);
                Assert.AreEqual(expected, actual);
            }

        }



        [TestMethod]
        public void BatchUpdateTest_LinkTable()
        {
            //先添加几条记录，然后批量修改

            DynamicEntity parentArea = new DynamicEntity("Area");
            parentArea["AreaName"] = "Testa中文 " + Guid.NewGuid().ToString();
            parentArea["ParentAreaId"] = 0;
            _session.Insert(_tableMapping, parentArea);


            int minId = 0;
            List<DynamicEntity> list = new List<DynamicEntity>();
            for (int i = 0; i < 5; i++)
            {
                DynamicEntity obj = new DynamicEntity("Area");
                obj["AreaName"] = "Testa中文 " + Guid.NewGuid().ToString();
                obj["ParentAreaId"] = parentArea["AreaId"];//将它设置为父对象
                _session.Insert(_tableMapping, obj);
                list.Add(obj);
                if (i == 0) minId = (int)obj["AreaId"];
            }

            //执行修改
            ConditionCollection cs = new ConditionCollection();
            cs.Add("ParentArea.areaName", ConditionOperator.Equal, parentArea["AreaName"]);


            DynamicEntity obj2 = new DynamicEntity("Area");
            obj2["AreaName"] = "update" + Guid.NewGuid().ToString();
            _session.BatchUpdate(_tableMapping, obj2, cs, "areaname");



            //是否还存在这个id  
            foreach (DynamicEntity item in list)
            {
                string expected = obj2.Get<string>("AreaName");
                object value = _session.ExecuteScalar("select AreaName from Test_Area where AreaId=" + item["AreaId"] + "");
                string actual = _session.ConvertDatabaseValue<string>(value);
                Assert.AreEqual(expected, actual);
            }

        }


        [TestMethod]
        public void BatchDeleteTest_SingleTable()
        {
            //先添加几条记录，然后批量修改
            int minId = 0;
            List<DynamicEntity> list = new List<DynamicEntity>();
            for (int i = 0; i < 5; i++)
            {
                DynamicEntity obj = new DynamicEntity("Area");
                obj["AreaName"] = "Testa中文 " + Guid.NewGuid().ToString();
                obj["ParentAreaId"] = 9;
                _session.Insert(_tableMapping, obj);
                list.Add(obj);
                if (i == 0) minId = obj.Get<int>("AreaId");
            }

            //执行删除
            ConditionCollection cs = new ConditionCollection();
            cs.Add("areaId", ConditionOperator.GreaterThanOrEqual, minId);
            _session.BatchDelete<Area>(_tableMapping, cs);



            //是否还存在  
            bool actual = _session.RecordExists("select AreaName from Test_Area where AreaId>=" + minId + "");
            bool expected = false;
            Assert.AreEqual(expected, actual);

        }



        [TestMethod]
        public void BatchDeleteTest_LinkTable()
        {
            //先添加几条记录，然后批量修改

            DynamicEntity parentArea = new DynamicEntity("Area");
            parentArea["AreaName"] = "Testa中文 " + Guid.NewGuid().ToString();
            parentArea["ParentAreaId"] = 0;
            _session.Insert(_tableMapping, parentArea);


            int minId = 0;
            List<DynamicEntity> list = new List<DynamicEntity>();
            for (int i = 0; i < 5; i++)
            {
                DynamicEntity obj = new DynamicEntity("Area");
                obj["AreaName"] = "Testa中文 " + Guid.NewGuid().ToString();
                obj["ParentAreaId"] = (int)parentArea["AreaId"];//将它设置为父对象
                _session.Insert(_tableMapping, obj);
                list.Add(obj);
                if (i == 0) minId = (int)obj["AreaId"];
            }

            //执行删除
            ConditionCollection cs = new ConditionCollection();
            cs.Add("ParentArea.areaName", ConditionOperator.Equal, parentArea["AreaName"]);
            _session.BatchDelete<Area>(_tableMapping, cs);




            //是否还存在  
            bool actual = _session.RecordExists("select AreaName from Test_Area where AreaId>=" + minId + "");
            bool expected = false;
            Assert.AreEqual(expected, actual);

        }




        [TestMethod]
        public void SelectTest()
        {

            DynamicEntity obj = new DynamicEntity("Area");
            obj["AreaName"] = "Testa中文 " + Guid.NewGuid().ToString();
            obj["ParentAreaId"] = 9;
            _session.Insert(_tableMapping, obj);


            DynamicEntity obj2 = new DynamicEntity("Area");
            obj2["AreaId"] = obj["AreaId"];
            bool actual = _session.Select(_tableMapping, obj2,ToStringArray(AreaProp.ALL));

            Assert.AreEqual(obj["AreaName"], obj2["AreaName"]);
            Assert.AreEqual(obj["ParentAreaId"], obj2["ParentAreaId"]);
            //测试返回
            Assert.AreEqual(true, actual);
        }



        [TestMethod]
        public void SelectTest_SpecifiedProperties()
        {

            DynamicEntity obj = new DynamicEntity("Area");
            obj["AreaName"] = "Testa中文 " + Guid.NewGuid().ToString();
            obj["ParentAreaId"] = 9;
            _session.Insert(_tableMapping, obj);

            DynamicEntity obj2 = new DynamicEntity("Area");
            obj2["AreaName"] = "Testa中文 " + Guid.NewGuid().ToString();
            obj2["ParentAreaId"] = obj["AreaId"];
            _session.Insert(_tableMapping, obj2);


            DynamicEntity obj9 = new DynamicEntity("Area");
            obj9["AreaId"] = obj2["AreaId"];
            obj9["AreaName"] = Guid.NewGuid().ToString();
            obj9["ParentAreaId"] = int.MinValue;
            obj9["ParentArea"] = new DynamicEntity("Area");
            obj9.Get<DynamicEntity>("ParentArea")["ParentAreaId"] = int.MinValue;//判断ParentArea是否有被重新实例化
            obj9.Get<DynamicEntity>("ParentArea")["AreaName"] = Guid.NewGuid().ToString();
            _session.Select(_tableMapping, obj9, new string[]{ "areaname", "parentarea.areaname"});

            Assert.AreEqual(obj2["AreaName"], obj9["AreaName"]);
            Assert.AreEqual(obj["AreaName"], obj9.Get<DynamicEntity>("ParentArea").Get<string>("AreaName"));
            Assert.AreEqual(int.MinValue, obj9.Get<DynamicEntity>("ParentArea").Get<int>("ParentAreaId"));

        }




        [TestMethod]
        public void SelectCountAndExistsTest_LinkTable()
        {
            int expected = 5;

            //第一次添加
            DynamicEntity obj = new DynamicEntity("Area");
            obj["AreaName"] = "Testa中文 " + Guid.NewGuid().ToString();
            obj["ParentAreaId"] = int.MinValue;
            _session.Insert(_tableMapping, obj);

            for (int i = 0; i < expected; i++)
            {
                DynamicEntity obj2 = new DynamicEntity("Area");
                obj2["AreaName"] = "Testa中文 " + Guid.NewGuid().ToString();
                obj2["ParentAreaId"] = obj["AreaId"];
                _session.Insert(_tableMapping, obj2);
            }

            //第二次添加
            obj["AreaName"] = "Testa中文 " + Guid.NewGuid().ToString();
            _session.Insert(_tableMapping, obj);
            for (int i = 0; i < expected; i++)
            {
                DynamicEntity obj2 = new DynamicEntity("Area");
                obj2["AreaName"] = "Testa中文 " + Guid.NewGuid().ToString();
                obj2["ParentAreaId"] = obj["AreaId"];
                _session.Insert(_tableMapping, obj2);
            }

            ConditionCollection cs = new ConditionCollection();
            cs.Add("parentarea.areaname", ConditionOperator.Equal, obj["AreaName"]);

            int actual = _session.SelectCount<Area>(_tableMapping, cs);

            Assert.AreEqual(expected, actual);


            bool actualExists = _session.Exists<Area>(_tableMapping, cs);
            Assert.AreEqual(true, actualExists);
        }



        [TestMethod]
        public void SelectCountAndExistsTest_SingleTable()
        {
            int expected = 5;

            //第一次添加
            DynamicEntity obj = new DynamicEntity("Area");
            obj["AreaName"] = "Testa中文 " + Guid.NewGuid().ToString();
            obj["ParentAreaId"] = int.MinValue;
            _session.Insert(_tableMapping, obj);

            for (int i = 0; i < expected; i++)
            {
                DynamicEntity obj2 = new DynamicEntity("Area");
                obj2["AreaName"] = "Testa中文 " + Guid.NewGuid().ToString();
                obj2["ParentAreaId"] = obj["AreaId"];
                _session.Insert(_tableMapping, obj2);
            }

            //第二次添加
            obj["AreaName"] = "Testa中文 " + Guid.NewGuid().ToString();
            _session.Insert(_tableMapping, obj);
            for (int i = 0; i < expected; i++)
            {
                DynamicEntity obj2 = new DynamicEntity("Area");
                obj2["AreaName"] = "Testa中文 " + Guid.NewGuid().ToString();
                obj2["ParentAreaId"] = obj["AreaId"];
                _session.Insert(_tableMapping, obj2);
            }

            ConditionCollection cs = new ConditionCollection();
            cs.Add("parentareaid", ConditionOperator.Equal, obj["AreaId"]);

            int actual = _session.SelectCount<Area>(_tableMapping, cs);

            Assert.AreEqual(expected, actual);


            bool actualExists = _session.Exists<Area>(_tableMapping, cs);
            Assert.AreEqual(true, actualExists);
        }




        [TestMethod]
        public void SelectCollectionTest()
        {
            Random r = new Random();

            #region 初始化一些数据
            #region 添加2个CustomerType
            List<DynamicEntity> customerTypes = new List<DynamicEntity>();

            DynamicEntity customerType1 = new DynamicEntity("CustomerType");
            customerType1["CustomerTypeName"] = Guid.NewGuid().ToString();
            _session.Insert(_tableMapping, customerType1);
            customerTypes.Add(customerType1);

            DynamicEntity customerType2 = new DynamicEntity("CustomerType");
            customerType2["CustomerTypeName"] = Guid.NewGuid().ToString();
            _session.Insert(_tableMapping, customerType2);
            customerTypes.Add(customerType2);
            #endregion
            #region 添加2个Area
            List<DynamicEntity> areas = new List<DynamicEntity>();

            DynamicEntity area1 = new DynamicEntity("Area");
            area1["AreaName"] = Guid.NewGuid().ToString();
            area1["ParentAreaId"] = 0;
            _session.Insert(_tableMapping, area1);
            customerTypes.Add(customerType1);
            areas.Add(area1);

            DynamicEntity area2 = new DynamicEntity("Area");
            area2["ParentAreaId"] = area1["AreaId"]; 
            area2["AreaName"] = Guid.NewGuid().ToString();
            _session.Insert(_tableMapping, area2);
            areas.Add(area2);
            #endregion
            #region 添加200个Customer
            for (int i = 0; i < 200; i++)
            {
                DynamicEntity customer = new DynamicEntity("Customer");
                customer["AccountTypeId"] = (AccountTypeId)r.Next(1, 4);
                customer["AreaId"] = areas[r.Next(0, 2)]["AreaId"];
                customer["CustomerName"] = Guid.NewGuid().ToString();
                customer["CustomerTypeId"] = customerTypes[r.Next(0, 2)]["CustomerTypeId"];
                _session.Insert(_tableMapping, customer);
            }
            #endregion
            #endregion

            QueryExpression q;
            List<Customer> result;
            int actualCount = 0;
            int expectedCount = 0;
            #region 不分页，返回count是否正确
            q = new QueryExpression();
            q.Selects.Add("*");
            q.Selects.Add("Area.*");
            q.Wheres.Add("area.areaname", ConditionOperator.Equal, areas[0]["AreaName"]);
            q.Wheres.Add("customertypeid", ConditionOperator.Equal, customerTypes[0]["CustomerTypeId"]);
            q.ReturnMatchedCount = true;
            result = new List<Customer>();
            actualCount = _session.SelectCollection<Customer>(_tableMapping, result, q);
            expectedCount = _session.ConvertDatabaseValue<int>(_session.ExecuteScalar("select count(*) from test_customer a left outer join test_area b on a.areaid=b.areaid where a.customertypeid=" + customerTypes[0]["CustomerTypeId"] + " and b.areaname='" + areas[0]["AreaName"] + "'"));
            Assert.AreEqual(expectedCount, actualCount);
            #endregion
            #region 不分页，返回count是否正确
            q.PageIndex = 2;
            q.PageSize = 3;
            actualCount = _session.SelectCollection<Customer>(_tableMapping, result, q);
            expectedCount = _session.ConvertDatabaseValue<int>(_session.ExecuteScalar("select count(*) from test_customer a left outer join test_area b on a.areaid=b.areaid where a.customertypeid=" + customerTypes[0]["CustomerTypeId"] + " and b.areaname='" + areas[0]["AreaName"] + "'"));
            Assert.AreEqual(expectedCount, actualCount);
            #endregion
            #region 不分页，返回count是否正确
            q.PageIndex = 2;
            q.PageSize = 3;
            q.ReturnMatchedCount = false;
            actualCount = _session.SelectCollection<Customer>(_tableMapping, result, q);
            expectedCount = result.Count;
            Assert.AreEqual(expectedCount, actualCount);
            #endregion


            #region 分页
            q = new QueryExpression();
            q.Selects.Add("area.areaname");
            q.Selects.Add("customername");
            q.Wheres.Add("area.areaname", ConditionOperator.Equal, areas[0]["AreaName"]);
            q.Wheres.Add("customertypeid", ConditionOperator.Equal, customerTypes[0]["CustomerTypeId"]);
            q.Orders.Add("customername", OrderType.Desc);
            q.PageIndex = 2;
            q.PageSize = 3;
            q.ReturnMatchedCount = false;
            result = new List<Customer>();
            actualCount = _session.SelectCollection<Customer>(_tableMapping, result, q);

            string actualKey = result[0].CustomerName + "_" + result[1].CustomerName + "_" + result[2].CustomerName;
            DataTable table = _session.ExecuteDataTable("select a.customerName,b.areaname from test_customer a left outer join test_area b on a.areaid=b.areaid where a.customertypeid=" + customerTypes[0]["CustomerTypeId"] + " and b.areaname='" + areas[0]["AreaName"] + "' order by a.customername desc");
            string expectedKey = table.Rows[3]["customerName"] + "_" + table.Rows[4]["customerName"] + "_" + table.Rows[5]["customerName"];
            Assert.AreEqual(expectedKey, actualKey);

            //父对象
            actualKey = result[0].Area.AreaName + "_" + result[1].Area.AreaName + "_" + result[2].Area.AreaName;
            expectedKey = table.Rows[3]["areaname"] + "_" + table.Rows[4]["areaname"] + "_" + table.Rows[5]["areaname"];
            Assert.AreEqual(expectedKey, actualKey);
            #endregion

            #region 分页_缓存测试
            q = new QueryExpression();
            q.Selects.Add("customername");//输出顺序换一下
            q.Selects.Add("area.areaname");//输出顺序换一下
            q.Wheres.Add("area.areaname", ConditionOperator.Equal, areas[0]["AreaName"]);
            q.Wheres.Add("customertypeid", ConditionOperator.Equal, customerTypes[0]["CustomerTypeId"]);
            q.Orders.Add("customername", OrderType.Desc);
            q.PageIndex = 2;
            q.PageSize = 4;
            q.ReturnMatchedCount = false;
            result = new List<Customer>();
            actualCount = _session.SelectCollection<Customer>(_tableMapping, result, q);
            //看日志中的sql语句

            //actualKey = result[0].CustomerName + "_" + result[1].CustomerName + "_" + result[2].CustomerName;
            //table = _session.ExecuteDataTable("select a.customerName,b.areaname from test_customer a left outer join test_area b on a.areaid=b.areaid where a.customertypeid=" + customerTypes[0].CustomerTypeId + " and b.areaname='" + areas[0].AreaName + "' order by a.customername desc");
            //expectedKey = table.Rows[3]["customerName"] + "_" + table.Rows[4]["customerName"] + "_" + table.Rows[5]["customerName"];
            //Assert.AreEqual(expectedKey, actualKey);

            ////父对象
            //actualKey = result[0].Area.AreaName + "_" + result[1].Area.AreaName + "_" + result[2].Area.AreaName;
            //expectedKey = table.Rows[3]["areaname"] + "_" + table.Rows[4]["areaname"] + "_" + table.Rows[5]["areaname"];
            //Assert.AreEqual(expectedKey, actualKey);
            #endregion
        }


        [TestMethod]
        public void EnumTest()
        {
            DynamicEntity obj = new DynamicEntity("Customer");
            obj["CustomerName"] = Guid.NewGuid().ToString();
            obj["AreaId"] = 0;
            obj["CustomerTypeId"] = 0;
            obj["AccountTypeId"] = AccountTypeId.Opened;
            _session.Insert(_tableMapping, obj);

            DynamicEntity obj2 = new DynamicEntity("Customer");
            obj2["CustomerId"] = obj["CustomerId"];
            _session.Select(_tableMapping, obj2,ToStringArray(CustomerProp.ALL));
            AccountTypeId expected = AccountTypeId.Opened;
            AccountTypeId actual = obj2.Get<AccountTypeId>("AccountTypeId");
            Assert.AreEqual(expected, actual);
        }
    }
}
